package Adventure;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * Main class for the game, will handle methods to start the game and end game.
 * @author Robin
 *
 */
public class Adventure 
{
	private static Scanner input;
	private static int menuChoice;
		
	public static void main(String[]args)
	{
		Adventure adventure = new Adventure();
		
		// Initialize the global variables
		input = new Scanner(System.in);
		menuChoice = 0;
		System.out.println("MAIN MENU");
		System.out.println("1) Start Adventure!");
		System.out.println("2) Exit Adventure!");
		
		
		try
		{
			menuChoice = input.nextInt();
			
			if(menuChoice == 1)
			{
				
				adventure.initializeAdventure();
			}
			else if(menuChoice == 2)
			{
				
				adventure.exitAdventure();
			}
			
		}catch(InputMismatchException me)
		{
			System.out.println("Wrong input");
			
		}
		
		
	}
	
	/**
	 * Initialize the Adventure, create and initialize the game objects and load assets to the game.
	 * Made so it calls the method to startAdventure in the end.
	 */
	protected void initializeAdventure()
	{		
		System.out.println("Initializing the game...");
		stopTime(500);
		System.out.println("Please hold...");
		stopTime(1000);
		System.out.println("While we wait... I should ask you, what is your name?");
		String playerName = input.nextLine();
		playerName = input.nextLine();
		System.out.println("Thank you for your cooperation, we are nearly done.");
		stopTime(1000);
		
		// Initialize the game objects
		Player player = new Player(playerName, 100, 0, 1);
		Level level1 = new Level(0, "Level 1");
		/***************************************************************************************
		//HOME: C:/Users/Robin/workspace/Adventure of the doublefnutt/src/Adventure/map/costomMap1
		 * LAPTOP: C:/Users/Robin/Documents/Repo Workspace/HOME REPO/src/Adventure/map/costomMap1
		 */
		
		level1.createAdvancedMap(100, 100, "C:/Users/Robin/Documents/Repo Workspace/HOME REPO/src/Adventure/map/costomMap1");
		
		try
		{
			level1.loadLevel(0, "C:/Users/Robin/Documents/Repo Workspace/HOME REPO/src/Adventure/map/costomMap1", 100, 100);
		}
		catch (FileNotFoundException e) 
		{
			System.out.println("Error, file not found!");
		}
		
		level1.generatePaths();
		level1.generateGameObjects();
		
		System.out.println("Initialization complete!");
		
		String startAdventureString = "Welcome to the Adventure! " + player.getPlayerName() + 
				"\nThe goal of this game is to collect all objects in the game and survive!\n"
				+ "Travel through the maze and locate objects to collect and foes to kill\n"
				+ "You will need a weapon and bullets to survive enemy encounters in the long run"
				+ "\nYou start the adventure in a dark moist maze and you see there are multiple ways to travel, "
				+ "which way do you go?";
		
		for(int stringIndex = 0; stringIndex < startAdventureString.length(); stringIndex++)
		{
			System.out.print(startAdventureString.charAt(stringIndex));
			stopTime(50);
		}
		
		
		startAdventure(player, level1);
	}
	
	/**
	 * Start's the adventure, with the pre-made assets and game objects.
	 * @param _player The main player.
	 */
	protected void startAdventure(Player _player, Level _level)
	{
		
		int random1 = _level.generateRandomNumber(1, _level.retrieveGameTiles().length - 2);
		int random2 = _level.generateRandomNumber(1, _level.retrieveGameTiles()[0].length - 2);
		_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
		
		stopTime(2000);
		System.out.println("\nCharacter placed in the maze! You may begin!");
		
		do
		{
			/* 
			 *  Check whether an tile have a trap on it - if so, tell it's story and damage/kill the player.
			 *  If the later one happens- OR if the player has lost all his health, call the function to exit the game
			 */
			for(int j = 0; j < _player.getCurrentLocation().retrieveTileObjects().size(); j++)
			{
				if(_player.getCurrentLocation().retrieveTileObjects().get(j) instanceof Trap)
				{
					System.out.println();
					((Trap)_player.getCurrentLocation().retrieveTileObjects().get(j)).printTrapLore();
					int trapDamage = ((Trap)_player.getCurrentLocation().retrieveTileObjects().get(j)).getTrapDamage();
					
					if(((Trap)_player.getCurrentLocation().retrieveTileObjects().get(j)).isDeadly())
					{
						_player.setPlayerStatus(false);
						exitAdventure();
					}
					else
					{
						_player.setPlayerHealth(_player.getPlayerHealth() - trapDamage);
						System.out.println(_player.getCurrentLocation().getTileNumber());
						if(_player.getPlayerHealth() <= 0)
						{
							_player.setPlayerStatus(false);
							exitAdventure();
						}
					}
				}
			}
			int previousLevel = _player.getPlayerLevel();
			if(_player.getCurrentLocation().hasEnemy())
			{
				if(_player.isEquippedItem() && _player.getEquipped() instanceof Weapon)
				{
					System.out.println("You have an weapon equipped and defended yourself, ending in the enemy getting slaughtered!");
					
					if(_player.hasAmmo())
					{
						_player.shoot();
						System.out.println("You shot and lost 1 bullet");
					}
					else
					{
						_player.setEquippedItem(false);
						System.out.println("You lost your weapon because of lack of bullets");
					}
					
					_player.getCurrentLocation().removeEnemy();
					
					_player.addExperience(10);
					
				}
				else
				{
					System.out.println(_player.getCurrentLocation().enemyName() + " has arrived to the tile, you fight with it and get damaged for " 
							+ (_player.getPlayerLevel() * 3 - _player.getPlayerArmor()) + ", and the fiend dies shortly after");
					_player.setPlayerHealth(_player.getPlayerHealth()-(_player.getPlayerLevel() * 3 - _player.getPlayerArmor()));
					_player.getCurrentLocation().removeEnemy();
					
					_player.addExperience(10);
					
				}
				
				int newLevel = _player.getPlayerLevel();
				
				if(newLevel > previousLevel)
				{
					System.out.println("Congratualations, you went up in level!");
					System.out.println("You reached level " + newLevel);
					_player.setPlayerHealth(_player.getPlayerHealth()+50);
					_player.setPlayerArmor(5);
				}
			}

			// Start the player options
			System.out.println("\n\nChoose your options!");
			
			ArrayList<Path> tmp = _player.getCurrentLocation().getTilePaths();
			for(int i = 0; i < tmp.size(); i++)
			{
				System.out.println(tmp.get(i).getPathNumber() + ") Go: " + tmp.get(i));
			}
			
			System.out.println("*********MENU************");
			
			System.out.println("8) Game Menu");

			System.out.println("******Tile Objects*******");
			
			int index = 9;
			for(int j = 0; j < _player.getCurrentLocation().retrieveTileObjects().size(); j++)
			{
				if(_player.getCurrentLocation().retrieveTileObjects().get(j) instanceof Trap)
				{
					_player.getCurrentLocation().retrieveTileObjects().remove(j);
					index--;
				}
				else
				{
					int secondIndex = index + j;
					
					if(_player.getCurrentLocation().retrieveTileObjects().get(j) instanceof Projectile)
					{
						System.out.println(secondIndex +") Tile Object: " + _player.getCurrentLocation().retrieveTileObjects().get(j) + ": " + _player.getCurrentLocation().getTileAmmo());
					}
					else
					{
						System.out.println(secondIndex +") Tile Object: " + _player.getCurrentLocation().retrieveTileObjects().get(j));
					}
					
				}
			}
			try
			{
				menuChoice = input.nextInt();
			}catch(InputMismatchException me)
			{
				System.out.println("Wrong input");
			}
			
			switch(menuChoice)
			{
			case 8:
			{
				System.out.println("You've chosen the option 8, please hold.");
				stopTime(1000);
				System.out.println("Game Menu Accessed!");
				System.out.println("1) Save Game ");
				System.out.println("2) Resume Game");
				System.out.println("3) Show Player Status");
				System.out.println("4) Inventory");
				System.out.println("5) Exit Game");
				try
				{
					menuChoice = input.nextInt();
				}catch(InputMismatchException me)
				{
					System.out.println("Wrong input");
				}
				System.out.println();
				
				if(menuChoice == 1)
				{
					System.out.println("This function is not yet available- check back in a later stage!");
				}
				else if(menuChoice == 2)
				{
					System.out.println("Resuming the game... exiting the game menu.");
					stopTime(500);
				}
				else if(menuChoice == 3)
				{
					System.out.println("The player's status is the following:");
					System.out.println();
					_player.printStatus();
					stopTime(500);
					System.out.println();
				}
				else if(menuChoice == 4)
				{
					System.out.println("Entering the player's inventory");
					System.out.println();
					stopTime(1000);
					_player.displayInventory();
					System.out.println(_player.getBackpack().size()+1 + ") Resume game ");
					System.out.println();
					System.out.println("What do you wish to do?");
					menuChoice = input.nextInt();
					
					if(menuChoice <= _player.getBackpack().size())
					{
						System.out.println("Press [E] to Equip and [D] to drop the item");
						String _tempString = input.next();
						
						if(_tempString.equalsIgnoreCase("E"))
						{
							if(_player.getBackpack().get(menuChoice-1).isEquippable())
							{
								_player.setEquipped(_player.getBackpack().get(menuChoice-1));
							}
							else
							{
								System.out.println("That object is not equippable.");
							}	
							
						}
						else if(_tempString.equalsIgnoreCase("D"))
						{
							if(_player.getBackpack().get(menuChoice-1) instanceof Projectile)
							{
								_player.getCurrentLocation().addObjectToTile(_player.dropItem(_player.getBackpack().get(menuChoice-1)));
								_player.getCurrentLocation().setTileAmmo(_player.getTotalAmmo());
							}
							else
							{
								_player.getCurrentLocation().addObjectToTile(_player.dropItem(_player.getBackpack().get(menuChoice-1)));
							}
						}
						else
						{
							System.out.println("Wrong input, resuming the game");
						}
					}
					else
					{
						System.out.println("Resuming game");
					}
				}
				else if(menuChoice == 5)
				{
					System.out.println("Terminating the program... please hold.");
					stopTime(1000);
					exitAdventure();
				}
				else
				{
					System.out.println("Wrong menu input - exiting the menu!");
				}
				
				break;
				
			}
			case 0: 
			{
				if(tmp.contains(Path.NORTH))
				{
					--random2;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went North");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 1:
			{
				if(tmp.contains(Path.WEST))
				{
					--random1;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went West");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 2:
			{
				if(tmp.contains(Path.SOUTH))
				{
					++random2;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went South");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 3:
			{
				if(tmp.contains(Path.EAST))
				{
					++random1;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went East");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 4:
			{
				if(tmp.contains(Path.NORTWEST))
				{
					--random1;
					--random2;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went Northwest");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 5:
			{
				if(tmp.contains(Path.NORTHEAST))
				{
					--random2;
					++random1;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went Northeast");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 6:
			{
				if(tmp.contains(Path.SOUTHWEST))
				{
					++random2;
					--random1;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went Southwest");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			case 7:
			{
				if(tmp.contains(Path.SOUTHEAST))
				{
					++random1;
					++random2;
					_player.setCurrentLocation(_level.retrieveGameTiles()[random1][random2], random1, random2);
					System.out.println("You went Southeast");
				}
				else
				{
					System.out.println("That path is not valid! please try again.");
				}
				break;
			}
			default: 
			{
				if(menuChoice > _player.getCurrentLocation().retrieveTileObjects().size() + 8)
				{
					System.out.println("Wrong input!");
				}
				else
				{
					System.out.println("Do you which to loot the item?[Y][N]");
					String yesNoInput = input.next();
					
					// If player enters 'Y' then add the item to the player's inventory and at the same time remove it
					// from the tile.
					if(yesNoInput.equalsIgnoreCase("Y"))
					{
						if(_player.getCurrentLocation().retrieveTileObjects().get(menuChoice-9) instanceof Projectile)
						{
							_player.pickupObject(((Projectile) _player.getCurrentLocation().retrieveTileObjects().remove(menuChoice-9)));
							_player.addBullet(_player.getCurrentLocation().getTileAmmo());
							_player.getCurrentLocation().setTileAmmo(0);
						}
						else
						{
							_player.pickupObject(_player.getCurrentLocation().retrieveTileObjects().remove(menuChoice-9));
						}
					}
					else
					{
						System.out.println("Putting the object down again");
					}
				}
			}
			}
			
			checkWinningCondition(_player, _level);

		}while(true);

	}
	
	/**
	 * Simple method which is called when the adventure is over
	 * Closing the Scanner and temporary objects that may reside in the game, 
	 * as well as closing the game with System.exit(0).
	 */
	protected void exitAdventure()
	{
		System.out.println("Exiting the Adventure!");
		input.close();
		System.exit(0);
	}
	
	// Simple helper method to stop the time of the game.
	protected void stopTime(int _milliseconds)
	{
		try 
		{
			Thread.sleep(_milliseconds);
		} 
		catch (InterruptedException e)
		{
			System.out.println("Interrupted the sleep mechanism");
		}
	}
	
	protected void checkWinningCondition(Player _player, Level _level)
	{
		int itemsLeft = 0;
		for(int k = 0; k < _level.retrieveGameTiles().length; k++)
		{
			for(int j = 0; j < _level.retrieveGameTiles()[k].length; j++)
			{
				if(_level.retrieveGameTiles()[k][j].retrieveTileObjects().size() != 0)
				{
					itemsLeft++;
				}
			}
		}
		
		if(itemsLeft == 0)
		{
			System.out.println("You are victorious!");
			exitAdventure();
		}
		else
		{
			System.out.println("There are ATLEAST " + itemsLeft + " Items left to collect" );
		}
		
	}

}
